package buff

import (
	"encoding/binary"
	"encoding/hex"
	"math"
)

type Buffer struct {
	endian binary.ByteOrder
	buf    []byte
	end    int
}

func NewBuffer(size int) *Buffer {
	return &Buffer{buf: make([]byte, size), endian: binary.LittleEndian, end: size}
}

func NewBufferBytes(buf []byte) *Buffer {
	return &Buffer{buf: buf, endian: binary.LittleEndian, end: len(buf)}
}

func (this *Buffer) Hex(pos, num int) string {
	end := pos + num
	if pos > this.end {
		return ""
	}
	if end > this.end {
		end = this.end
	}
	return hex.EncodeToString(this.buf[pos:end])
}

func (this *Buffer) Length() int {
	return this.end
}

//重新设置为新数据
func (this *Buffer) ResetData(buf []byte) {
	this.end = len(buf)
	if this.end > len(this.buf) {
		this.buf = make([]byte, this.end)
	}
	copy(this.buf, buf)
}

func (this *Buffer) Clear() {
	this.end = 0
}

func (this *Buffer) Limit(end int) {
	if len(this.buf) > end {
		this.end = end
	}
}

func (this *Buffer) Bytes() []byte {
	return this.buf[:this.end]
}

func check(buf []byte, pos int) {
	if len(buf) < pos {
		panic("Buffer overflow.")
	}
}

func (this *Buffer) PutByte(pos int, value byte) {
	check(this.buf, pos+1)
	this.buf[pos] = value
	return
}
func (this *Buffer) Byte(pos int) (value byte) {
	check(this.buf, pos+1)
	value = this.buf[pos]
	return
}

func (this *Buffer) PutUint16(pos int, value uint16) {
	check(this.buf, pos+2)
	this.endian.PutUint16(this.buf[pos:], value)
	return
}
func (this *Buffer) Uint16(pos int) (value uint16) {
	check(this.buf, pos+2)
	value = this.endian.Uint16(this.buf[pos:])
	return
}

func (this *Buffer) PutUint32(pos int, value uint32) {
	check(this.buf, pos+4)
	this.endian.PutUint32(this.buf[pos:], value)
	return
}

func (this *Buffer) Uint32(pos int) (value uint32) {
	check(this.buf, pos+4)
	value = this.endian.Uint32(this.buf[pos:])
	return
}

func (this *Buffer) PutFloat(pos int, value float32) {
	check(this.buf, pos+4)
	this.endian.PutUint32(this.buf[pos:], math.Float32bits(value))
	return
}

func (this *Buffer) Float32(pos int) float32 {
	val := this.Uint32(pos)
	return math.Float32frombits(val)
}

func (this *Buffer) PutArray(pos int, value []byte) {
	check(this.buf, pos+len(value))
	copy(this.buf[pos:pos+len(value)], value)
	return
}
func (this *Buffer) Array(pos int, size int) []byte {
	check(this.buf, pos+size)
	return this.buf[pos : pos+size]
}
